/**
 * Copyright 2023 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
Auto-generated by: https://github.com/pmndrs/gltfjsx
Command: npx gltfjsx@6.1.4 public/Doggo07.glb -t
*/
import * as THREE from 'three'
import React, { useEffect, useRef } from 'react'
import { useGLTF, useAnimations } from '@react-three/drei'
import { GLTF } from 'three-stdlib'
import {Blendshapes} from '../../apis/mediapipe_audio_blendshapes';
import * as talkingHead from '../../apis/talkingHead';
import { AnimationAction } from 'three';
type GLTFResult = GLTF & {
  nodes: {
    Body: THREE.Mesh
    Head: THREE.Mesh
  }
  materials: {
    ['Dog_body_baked.001']: THREE.MeshStandardMaterial
    ['Dog_head_baked.001']: THREE.MeshStandardMaterial
  }
}
type ActionName = 'Expression' | 'KeyAction' | 'HeadMovement' | 'BodyAction'
type GLTFActions = Record<ActionName, THREE.AnimationAction>
function updateBlendshapes(node: THREE.Mesh, blendshapes: Blendshapes /* Map<string, number> */ ) {
  if (!node.morphTargetDictionary) {
    return;
  }
  if (!node.morphTargetInfluences) {
    return;
  }
  // console.log(blendshapes)
  // console.log(node.morphTargetDictionary)
  for (const name in blendshapes) {
    const value = blendshapes[name];
    if (!Object.keys(node.morphTargetDictionary).includes(name)) {
      continue;
    }
    const idx = node.morphTargetDictionary[name];
    node.morphTargetInfluences[idx] = value;
  }
}
export function Doggo(props: JSX.IntrinsicElements['group']) {
  const group = useRef<THREE.Group>()
  const { nodes, materials, animations } = useGLTF('/Doggo07.glb') as GLTFResult
  const { ref, actions } = useAnimations(animations, group)
  const keyactionsStoped = useRef<boolean>(false);
  useEffect(()=>{
    setInterval(() => {
      if (talkingHead.audioBlendshapes === null) return;
      const blendShapesMapping = talkingHead.audioBlendshapes!.getBlendshapes();
    if (!keyactionsStoped.current && talkingHead.lastAudioT > 0.0) {
      actions.KeyAction!.stop()
      keyactionsStoped.current = true;
    }
      updateBlendshapes(nodes.Head, blendShapesMapping);
    }, 50);
  }, [nodes]);
  useEffect(() => {
    actions.HeadMovement!.play()
    if (talkingHead.lastAudioT === 0.0) {
      actions.KeyAction!.play()
    }
  });
  return (
    <group ref={ref as React.Ref<THREE.Group>} {...props} dispose={null} position={[0,0,4.5]}>
      <group name="Scene">
        <mesh name="Body" geometry={nodes.Body.geometry} material={materials['Dog_body_baked.001']} position={[0, -2.36, -2.84]} rotation={[2.24, 0, 0]} scale={[2.74, 2.74, 3.06]} />
        <mesh name="Head" geometry={nodes.Head.geometry} material={materials['Dog_head_baked.001']} morphTargetDictionary={nodes.Head.morphTargetDictionary} morphTargetInfluences={nodes.Head.morphTargetInfluences} position={[0.05, 0.56, -2.63]} rotation={[Math.PI / 2, 0, 0]} scale={0.2} />
      </group>
    </group>
  )
}
useGLTF.preload('/Doggo07.glb')
